

// WebSocket 服务 - 实现单例模式，支持心跳和多组件共享连接
class WebSocketService {
  private static instance: WebSocketService
  private ws: WebSocket | null = null
  private url: string = 'wss://wss.fastht.com/wss'
  private reconnectInterval: number = 1000 // 初始重连间隔(ms)
  private maxReconnectInterval: number = 30000 // 最大重连间隔(ms)
  private reconnectAttempts: number = 0 // 当前重连次数
  private heartBeatInterval: number = 60 * 1000
  private heartBeatTimer: NodeJS.Timeout | null = null
  private reconnectTimer: NodeJS.Timeout | null = null
  private pingTimeout: NodeJS.Timeout | null = null
  private isConnecting: boolean = false
  private messageHandlers: Map<string, Set<Function>> = new Map()
  private defaultHandler: Function | null = null
  private eventListeners: Map<string, Set<Function>> = new Map()
  private pingTimeoutInterval: number = 10 * 1000 // 心跳超时时间(ms)
  private maxReconnectAttempts: number = 10 // 最大重连次数
  private isSupported: boolean = typeof WebSocket !== 'undefined'

  // 私有构造函数，防止外部直接实例化
  private constructor() {}

  // 获取单例实例
  public static getInstance(): WebSocketService {
    if (!WebSocketService.instance) {
      WebSocketService.instance = new WebSocketService()
    }
    return WebSocketService.instance
  }

  // 连接WebSocket
  public connect(url?: string): void {
    // 检查浏览器兼容性
    if (!this.isSupported) {
      console.error('当前浏览器不支持WebSocket')
      this.emitEvent('error', new Error('当前浏览器不支持WebSocket'))
      return
    }

    if (this.ws?.readyState === WebSocket.OPEN || this.isConnecting) {
      return
    }

    // 如果提供了新的URL，更新它
    if (url) {
      this.url = url
    }

    this.isConnecting = true
    try {
      this.ws = new WebSocket(this.url)

      this.ws.onopen = () => {
        console.log('WebSocket 连接成功')
        this.isConnecting = false
        this.reconnectAttempts = 0 // 重置重连次数
        this.startHeartBeat()
        this.clearReconnectTimer()
        this.emitEvent('open')
      }

      this.ws.onmessage = (event) => {
        try {
          // 重置心跳超时
          this.resetPingTimeout()
          
          // 处理心跳响应
          if (event.data === '"heartbeat"') {
            return
          }
          
          // 尝试解析JSON数据
          let data: SocketMessage
          try {
            console.log(11, event.data);
            
            const { message_type, data: messageData, ...other} = JSON.parse(event.data)
            data = {
              message_type,
              data: {
                ...(messageData || {}),
                ...(other || {})
              }
            }
          } catch (e) {
            console.log(e);
            
            // 如果不是JSON格式，直接使用原始数据
            data = { message_type: 'group_chat', data: {} }
          }
          
          // 触发类型化的消息处理器
          const messageType = data.message_type || 'default'
          
          if (this.messageHandlers.has(messageType)) {
            this.messageHandlers.get(messageType)?.forEach(handler => {
              try {
                handler(data)
              } catch (error) {
                console.error(`消息处理器错误 (${messageType}):`, error)
              }
            })
          }
          
          // 触发默认消息处理器
          if (this.defaultHandler) {
            try {
              this.defaultHandler(data)
            } catch (error) {
              console.error('默认消息处理器错误:', error)
            }
          }
        } catch (error) {
          console.error('消息处理错误:', error)
          this.emitEvent('error', error)
        }
      }

      this.ws.onclose = (event) => {
        console.log(`WebSocket 连接关闭: ${event.code} - ${event.reason}`)
        this.isConnecting = false
        this.stopHeartBeat()
        this.emitEvent('close', event)
        
        // 只有在非正常关闭时才重连
        if (!event.wasClean) {
          this.scheduleReconnect()
        }
      }

      this.ws.onerror = (error) => {
        console.error('WebSocket 错误:', error)
        this.isConnecting = false
        this.emitEvent('error', error)
      }
    } catch (error) {
      console.error('WebSocket 连接失败:', error)
      this.isConnecting = false
      this.emitEvent('error', error)
      this.scheduleReconnect()
    }
  }

  // 断开连接
  public disconnect(): void {
    this.stopHeartBeat()
    this.clearReconnectTimer()
    if (this.ws) {
      // 正常关闭连接
      this.ws.close(1000, '手动断开连接')
      this.ws = null
    }
  }

  // 重新连接
  public reconnect(): void {
    this.disconnect()
    setTimeout(() => {
      this.connect()
    }, 100)
  }

  // 发送消息
  public send(message: SocketMessage | any): boolean {
    // 确保消息符合SocketMessage格式
    

    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      console.warn('WebSocket 未连接，无法发送消息')
      this.emitEvent('sendFailed', { data: message, error: 'WebSocket 未连接' })
      return false
    }

    try {
      const messageString = JSON.stringify({
        message_type: message.message_type,
        ...message.data
      })
      this.ws.send(messageString)
      this.emitEvent('messageSent', message)
      return true
    } catch (error) {
      console.error('WebSocket 发送消息失败:', error)
      this.emitEvent('sendFailed', { data: message, error })
      return false
    }
  }

  // 发送文本消息
  public sendText(text: string): boolean {
    return this.send({ type: 'text', content: text })
  }

  // 订阅指定类型的消息
  public subscribe(messageType: string, handler: Function): void {
    if (!this.messageHandlers.has(messageType)) {
      this.messageHandlers.set(messageType, new Set())
    }
    this.messageHandlers.get(messageType)?.add(handler)
  }

  // 取消订阅指定类型的消息
  public unsubscribe(messageType: string, handler: Function): void {
    if (this.messageHandlers.has(messageType)) {
      this.messageHandlers.get(messageType)?.delete(handler)
      // 如果没有处理器了，删除该类型
      if (this.messageHandlers.get(messageType)?.size === 0) {
        this.messageHandlers.delete(messageType)
      }
    }
  }

  // 设置默认消息处理器
  public setDefaultHandler(handler: Function): void {
    this.defaultHandler = handler
  }

  // 移除默认消息处理器
  public removeDefaultHandler(): void {
    this.defaultHandler = null
  }

  // 开始心跳
  private startHeartBeat(): void {
    this.stopHeartBeat()
    
    // 发送心跳包
    const sendPing = () => {
      if (this.ws?.readyState === WebSocket.OPEN) {
        console.log(11111);
        
        this.send({ message_type: "heartbeat" })
        // 设置心跳超时
        this.pingTimeout = setTimeout(() => {
          console.warn('WebSocket 心跳超时，关闭连接并尝试重连')
          this.ws?.close(1006, '心跳超时')
        }, this.pingTimeoutInterval)
      }
    }
    
    this.heartBeatTimer = setInterval(sendPing, this.heartBeatInterval)
    // 立即发送一次心跳
    sendPing()
  }

  // 重置心跳超时
  private resetPingTimeout(): void {
    if (this.pingTimeout) {
      clearTimeout(this.pingTimeout)
      this.pingTimeout = null
    }
  }

  // 停止心跳
  private stopHeartBeat(): void {
    if (this.heartBeatTimer) {
      clearInterval(this.heartBeatTimer)
      this.heartBeatTimer = null
    }
    this.resetPingTimeout()
  }

  // 安排重连 - 使用指数退避策略
  private scheduleReconnect(): void {
    // 检查是否达到最大重连次数
    if (this.maxReconnectAttempts > 0 && this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error(`已达到最大重连次数(${this.maxReconnectAttempts})，停止重连`)
      this.emitEvent('maxReconnectAttemptsReached', { attempts: this.reconnectAttempts })
      return
    }

    this.clearReconnectTimer()
    
    // 计算指数退避重连间隔（带随机因子）
    this.reconnectAttempts++
    const baseInterval = Math.min(
      this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1),
      this.maxReconnectInterval
    )
    // 添加随机因子，避免多客户端同时重连
    const jitter = Math.random() * 1000
    const reconnectDelay = baseInterval + jitter
    
    console.log(`尝试重新连接 WebSocket... (第 ${this.reconnectAttempts} 次, 延迟: ${Math.round(reconnectDelay)}ms)`)
    
    this.reconnectTimer = setTimeout(() => {
      this.connect()
    }, reconnectDelay)
  }

  // 添加事件监听器
  public on(event: string, listener: Function): void {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, new Set())
    }
    this.eventListeners.get(event)?.add(listener)
  }

  // 移除事件监听器
  public off(event: string, listener: Function): void {
    if (this.eventListeners.has(event)) {
      this.eventListeners.get(event)?.delete(listener)
      if (this.eventListeners.get(event)?.size === 0) {
        this.eventListeners.delete(event)
      }
    }
  }

  // 触发事件
  private emitEvent(event: string, ...args: any[]): void {
    if (this.eventListeners.has(event)) {
      this.eventListeners.get(event)?.forEach(listener => {
        try {
          listener(...args)
        } catch (error) {
          console.error(`事件处理器错误 (${event}):`, error)
        }
      })
    }
  }

  // 清除重连定时器
  private clearReconnectTimer(): void {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
      this.reconnectTimer = null
    }
  }

  // 获取连接状态
  public getReadyState(): number {
    return this.ws?.readyState || WebSocket.CLOSED
  }

  // 获取连接状态文本
  public getReadyStateText(): string {
    const state = this.getReadyState()
    switch (state) {
      case WebSocket.CONNECTING:
        return '连接中'
      case WebSocket.OPEN:
        return '已连接'
      case WebSocket.CLOSING:
        return '关闭中'
      case WebSocket.CLOSED:
        return '已关闭'
      default:
        return '未知状态'
    }
  }

  // 配置WebSocket服务
  public configure(options: {
    url?: string
    reconnectInterval?: number
    maxReconnectInterval?: number
    heartBeatInterval?: number
    pingTimeoutInterval?: number
    maxReconnectAttempts?: number
  }): void {
    if (options.url) this.url = options.url
    if (options.reconnectInterval !== undefined) this.reconnectInterval = options.reconnectInterval
    if (options.maxReconnectInterval !== undefined) this.maxReconnectInterval = options.maxReconnectInterval
    if (options.heartBeatInterval !== undefined) this.heartBeatInterval = options.heartBeatInterval
    if (options.pingTimeoutInterval !== undefined) this.pingTimeoutInterval = options.pingTimeoutInterval
    if (options.maxReconnectAttempts !== undefined) this.maxReconnectAttempts = options.maxReconnectAttempts
  }

  // 检查WebSocket是否可用
  public isWebSocketSupported(): boolean {
    return this.isSupported
  }
}

// 导出单例实例
export const wsService = WebSocketService.getInstance()

// 导出类型定义
export type {
  WebSocketService,
  SocketMessage,
  MessageType
}